<script setup lang="ts">
import { UploadFile, UploadFiles, UploadRawFile } from "element-plus";
import VueCropper from "vue-cropper/src/vue-cropper.vue";
import to from "await-to-js";
import {
  postToOSS as postToOssApi,
  getOssAuth as getOssAuthApi,
  linkCover as linkCoverApi,
} from "@/service/api/course/image/CoverApi.ts";
import UploadButton from "@/components/Upload/uploadButton.vue";
import {
  createOrganizationCover,
  updateOrganizationCover,
} from "@/service/api/school/image";

const props = defineProps({
  modelValue: {
    type: Boolean,
    default: false,
  },
  /**
   * 对应的组织id
   */
  organizationId: {
    type: String,
    required: true,
  },
  /**
   * 封面类型
   */
  coverType: {
    type: Number,
    required: true,
  },
  /**
   * 是否已经上传过这个类型的封面
   */
  isLinked: {
    type: Boolean,
    required: true,
  },
  /**
   * 已上传封面的url
   */
  linkedCoverUrl: {
    type: String,
    required: false,
  },
  /**
   * 封面的宽度要求
   */
  cropWidth: {
    type: Number,
    required: true,
  },
  /**
   * 封面的高度要求
   */
  cropHeight: {
    type: Number,
    required: true,
  },
  /**
   * 是否允许操作
   */
  isOperable: {
    type: Boolean,
    required: true,
  },
});

/**
 * 定义事件
 */
const emit = defineEmits(["update:modelValue"]);

const attrs = useAttrs();

/**
 * 是否已经选择图片
 */
const isSelected = ref(false);
/**
 * 是否已经上传图片
 */
const isUploaded = ref(false);

/**
 * 选择的原始图片
 */
const originalCoverFile = ref<UploadRawFile>(<UploadRawFile>{});
/**
 * 裁剪后的图片
 */
const coverFile = ref();
/**
 * 裁剪后的图片的url，用于预览
 */
const coverFileUrl = ref(props.linkedCoverUrl);
/**
 * 是否显示裁剪对话框
 */
const isCropDialogShow = ref(false);
/**
 * 裁剪组件
 */
const cropperRef: any = ref({});

/**
 * 实时预览裁剪的图片
 */
const previewCrop: any = ref({});

/**
 * 裁剪选项类型
 */
interface Options {
  img: string | ArrayBuffer | null; // 裁剪图片的地址
  info: true; // 裁剪框的大小信息
  outputSize: number; // 裁剪生成图片的质量 [1至0.1]
  outputType: "jpeg"; // 裁剪生成图片的格式
  canScale: boolean; // 图片是否允许滚轮缩放
  autoCrop: boolean; // 是否默认生成截图框
  autoCropWidth: number; // 默认生成截图框宽度
  autoCropHeight: number; // 默认生成截图框高度
  fixedBox: boolean; // 固定截图框大小 不允许改变
  fixed: boolean; // 是否开启截图框宽高固定比例
  fixedNumber?: Array<number>; // 截图框的宽高比例  需要配合centerBox一起使用才能生效
  full: boolean; // 是否输出原图比例的截图
  canMoveBox: boolean; // 截图框能否拖动
  original: boolean; // 上传图片按照原始比例渲染
  centerBox: boolean; // 截图框是否被限制在图片里面
  infoTrue: boolean; // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
  enlarge: number;
}

/**
 * 裁剪选项
 */
const options: Options = reactive({
  img: "", // 需要剪裁的图片
  autoCrop: true, // 是否默认生成截图框
  autoCropWidth: props.cropWidth, // 默认生成截图框的宽度
  autoCropHeight: props.cropHeight, // 默认生成截图框的长度
  fixedBox: true, // 是否固定截图框的大小 不允许改变
  info: true, // 裁剪框的大小信息
  outputSize: 1, // 裁剪生成图片的质量 [1至0.1]
  outputType: "jpeg", // 裁剪生成图片的格式
  canScale: true, // 图片是否允许滚轮缩放
  fixed: true, // 是否开启截图框宽高固定比例
  fixedNumber: [props.cropWidth, props.cropHeight], // 截图框的宽高比例 需要配合centerBox一起使用才能生效
  full: false, // 是否输出原图比例的截图
  canMoveBox: true, // 截图框能否拖动
  original: false, // 上传图片按照原始比例渲染
  centerBox: false, // 截图框是否被限制在图片里面
  infoTrue: false, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
  enlarge: 2,
});

interface IInitCoverParams {
  OSSAccessKeyId: string;
  callback: string;
  dir: string;
  expire: string;
  host: string;
  policy: string;
  service: string;
  signature: string;
  file: string;
  key: string;
}

/**
 * 上传封面请求参数原型
 */
const initCoverParams: IInitCoverParams = {
  OSSAccessKeyId: "",
  callback: "",
  dir: "",
  expire: "",
  host: "",
  policy: "",
  service: "",
  signature: "",
  file: "",
  key: "",
};

/**
 * 上传封面请求参数
 */
const coverParams = reactive({ value: { ...initCoverParams } });

// 关联封面与课程的请求对象
const initLinkCoverBO = {
  organizationId: "",
  type: "",
  cover: "",
};

const linkCoverBO = reactive({ ...initLinkCoverBO });

/**
 * 上传凭证
 */
const getOssAuthBO = reactive({
  originalFileName: "",
});

/**
 * 预览图片地址
 */
const previewImageUrl = ref("");

/**
 * 是否显示预览对话框
 */
const isPreviewDialogShow = ref(false);

/**
 * 选择图片
 *
 * @param uploadFile
 * @param uploadFiles
 */
const handleSelect = (uploadFile: UploadFile, uploadFiles: UploadFiles) => {
  console.log(uploadFile, uploadFiles);
  originalCoverFile.value = uploadFile.raw ?? <UploadRawFile>{};
  showCropDialog();
};

/**
 * 超过一张时触发，重选图片
 * @param files
 */
const handleReselect = (files: File[]) => {
  originalCoverFile.value = files[0] as UploadRawFile;
  showCropDialog();
};

/**
 * 显示裁剪图片对话框
 */
const showCropDialog = () => {
  options.img = URL.createObjectURL(originalCoverFile.value);
  isCropDialogShow.value = true;
  // dialogStatus.value.isCropper1 = true;
  // emit('select-cover', originalCoverFile1.value,
  // );
};

/**
 * 完成裁剪
 */
const finishCrop = () => {
  // cropperRef.value.getCropData((data: any) => {
  //   // console.log("获取截图的 base64 数据:", data);
  //   // data为base64图片，供接口使用
  // });
  cropperRef.value.getCropBlob((data: any) => {
    console.log("获取截图的 blob 数据:", data);
    // 下面是将blob转为formData
    // let formData = new FormData();
    // formData.append("file", data, new Date().getTime() + ".jpg");
    // console.log("formData:", formData);
    // 下面是将blob转换为file
    data.lastModifiedDate = new Date(); // 文件最后的修改日期
    coverFile.value = new File([data], originalCoverFile.value.name, {
      type: data.type,
      lastModified: Date.now(),
    });
    coverFileUrl.value = URL.createObjectURL(coverFile.value);
  });
  isSelected.value = true;
  isUploaded.value = false;
  isCropDialogShow.value = false;
  emit("update:modelValue", true);
};

/**
 * 实时预览裁剪图片
 * @param data
 */
const realTimeCrop = (data: any) => {
  // console.log("realTime:", data);
  previewCrop.value = data;
  console.log(previewCrop.value);
};

/**
 * 处理上传图片
 */
const handleUpload = async () => {
  console.log("upload",coverFile);
  const response = await to(getOssAuth(originalCoverFile.value.name));

  if (response) {
    console.log(coverParams.value);
    
    const formData = new FormData();
    formData.append("key", coverParams.value.key);
    formData.append("OSSAccessKeyId", coverParams.value.OSSAccessKeyId);
    formData.append("policy", coverParams.value.policy);
    formData.append("signature", coverParams.value.signature);
    formData.append("x:cover", "cover1");
    formData.append("success_action_status", "200"); // 上传成功返回的状态码，不设置则是204
    formData.append("callback", coverParams.value.callback);
    formData.append("file", coverFile.value); // 一定在最后

    const res = await postToOssApi(formData);
    console.log(res);
    // 是否上传成功
    if (res.status === 200) {
      ElMessage({
        type: "success",
        message: "上传成功",
      });

      // 是否拿到上传的图片的id
      if (res.data.code === 200) {
        linkCoverBO.organizationId = props.organizationId;
        linkCoverBO.cover = res.data.data.url;
        linkCoverBO.type = String(props.coverType);
        console.log(linkCoverBO.cover);
        const [err] =
          props.isLinked === true || isUploaded.value === true
            ? await to(updateOrganizationCover(linkCoverBO))
            : await to(createOrganizationCover(linkCoverBO));

        if (!err) {
          isUploaded.value = true;
          emit("update:modelValue", false);
          // isLinked.value = true;

          ElMessage({
            type: "success",
            message: "封面和学校绑定成功",
          });
        } else {
          ElMessage({
            type: "error",
            message: "封面和学校绑定失败",
          });
        }
      } else {
        ElMessage({
          type: "error",
          message: "无法获取上传文件的链接",
        });
      }
    } else {
      ElMessage({
        type: "error",
        message: "上传失败，请联系管理员",
      });
    }
  }
};

/**
 * 获取OSS上传凭证
 * @param originalFilename
 */
const getOssAuth = async (originalFilename: string): Promise<boolean> => {
  getOssAuthBO.originalFileName = originalFilename;
  const [err, res] = await to(getOssAuthApi(getOssAuthBO));
  console.log(res);
  if (!err) {
    coverParams.value = { ...res.data };
    return true;
  }
  return false;
};

/**
 * 查看已上传图片的
 * @param url
 */
const handlePreview = (url: any) => {
  console.log("url", url);
  previewImageUrl.value = url;
  isPreviewDialogShow.value = true;
};

/**
 * 关闭预览
 */
const handleClosePreview = () => {
  isPreviewDialogShow.value = false;
};
// 销毁前的回调
onBeforeUnmount(() => {
  coverFileUrl.value = props.linkedCoverUrl;
  console.log(1, coverFileUrl.value);
});
</script>

<template>
  <div class="upload-cover-image">
    <div :class="'cover-upload' + props.coverType">
      <el-upload
        v-if="isOperable"
        v-bind="attrs"
        action="#"
        :accept="'image/png, image/jpeg'"
        :show-file-list="false"
        list-type="picture-card"
        :limit="1"
        :auto-upload="false"
        :on-change="handleSelect"
        :on-exceed="handleReselect"
      >
        <!--          ref="uploadCoverEl2"-->
        <img
          v-if="props.isLinked && !isSelected"
          style="width: 100%; height: 100%"
          :src="props.linkedCoverUrl"
          :alt="'cover' + coverType"
        />
        <div
          v-if="
            !isSelected &&
            (props.linkedCoverUrl === null || props.linkedCoverUrl === '')
          "
        >
          <el-tooltip content="选择图片" placement="top" :enterable="false">
            <el-button
              link
              type="primary"
              icon="UploadFilled"
              size="large"
              v-hasPermi="['course:course:edit']"
            ></el-button>
          </el-tooltip>
        </div>
        <div
          v-else
          class="el-upload-list__item-thumbnail"
          v-html="previewCrop.html"
        ></div>
      </el-upload>
      <div v-else>
        <img
          v-if="props.linkedCoverUrl"
          class="detailImg"
          :style="{
            border: 'solid 1px #999',
            width: props.cropWidth + 'px',
            height: props.cropHeight + 'px',
          }"
          :src="props.linkedCoverUrl"
          :alt="'cover' + coverType"
        />

        <el-empty v-else :image-size="150" description="未上传图片" />
      </div>

      <div class="image-buttons">
        <upload-button
          v-show="isOperable"
          :is-uploaded="isUploaded"
          :is-selected="isSelected"
          :is-linked="isLinked"
          @click="handleUpload"
        ></upload-button>
        <!--        <el-button-->
        <!--          v-show="isOperable"-->
        <!--          link-->
        <!--          :disabled="!isSelected"-->
        <!--          style="font-size: 14px; margin-left: 50px"-->
        <!--          type="success"-->
        <!--        >-->
        <!--          调整-->
        <!--        </el-button>-->
        <!--        @click="handleRecropCover2">-->
        <el-button
          v-if="isOperable || (!isOperable && linkedCoverUrl)"
          type="success"
          link
          :disabled="!isLinked && !isSelected"
          @click="handlePreview(coverFileUrl)"
          class="image-buttons-right"
        >
          查看详情
        </el-button>
      </div>
    </div>
  </div>

  <!--  裁剪对话框-->
  <el-dialog v-model="isCropDialogShow" title="图片裁剪" center width="900">
    <div style="width: 100%; height: 60vh">
      <vue-cropper
        ref="cropperRef"
        :img="options.img"
        :autoCropWidth="options.autoCropWidth"
        :autoCropHeight="options.autoCropHeight"
        :fixedNumber="options.fixedNumber"
        :centerBox="options.centerBox"
        :canScale="options.canScale"
        :infoTrue="options.infoTrue"
        :auto-crop="options.autoCrop"
        :fixed-box="options.fixedBox"
        :fixed="options.fixed"
        :info="false"
        @realTime="realTimeCrop"
      >
      </vue-cropper>
    </div>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="isCropDialogShow = false">取消</el-button>
        <el-button @click="cropperRef.refresh()">重置</el-button>
        <el-button type="primary" @click="finishCrop"> 确认 </el-button>
      </span>
    </template>
  </el-dialog>

  <!--  预览对话框-->
  <!--  <el-dialog v-model="isPreviewDialogShow" :title="coverName" :center="true" class="preview_dialog">-->
  <!--    <el-scrollbar>-->
  <!--      <img w-full :src="previewImageUrl" alt="Preview Image" />-->
  <!--    </el-scrollbar>-->
  <!--  </el-dialog>-->

  <el-image-viewer
    v-if="isPreviewDialogShow"
    :url-list="[previewImageUrl]"
    teleported
    @close="handleClosePreview"
  />
</template>

<style scoped lang="scss">
.upload-cover-image {
  :deep(.el-upload--picture-card) {
    width: v-bind("cropWidth + 'px'");
    height: v-bind("cropHeight + 'px'");
    overflow: hidden;
  }
}

/*
.cover1 {
  :deep(.el-upload--picture-card) {
    width: 694px;
    height: 390px;
    overflow: hidden;
  }
}

.cover2 {
  :deep(.el-upload--picture-card) {
    width: 180px;
    height: 244px;
    overflow: hidden;
  }
}

.cover3 {
  :deep(.el-upload--picture-card) {
    width: 170px;
    height: 170px;
    overflow: hidden;
  }
}
*/

.preview_dialog {
  :deep(.el-dialog__body) {
    overflow: auto;
  }
}

.image-buttons {
  margin-top: 16px;
}

.image-buttons-right {
  margin-left: 16px;
}
</style>
